﻿(function () {
    "use strict";

    var newCreate = false;
    var db = null;
    var pageStore = null;
    var photoStore = null;

    WinJS.Namespace.define("PhotoDB", {
        createDB: createDB,
        deleteDB: deleteDB,
        openDB: openDB,
        db: db,
        initializeGallery: initializeGallery,
        updateImgSize: updateImgSize,
        updateUrl: updateUrl,
        updatePage: updatePage,
        updateImage: updateImage,
    });

    deleteDB();

    function createDB() {
        var dbRequest = window.indexedDB.open("PhotoDB", 1);

        // Add asynchronous callback functions
        dbRequest.onerror = function () { WinJS.log && WinJS.log("Error creating database.", "PhotoDB", "error"); };
        dbRequest.onsuccess = function (evt) { dbSuccess(evt); };
        dbRequest.onupgradeneeded = function (evt) { dbVersionUpgrade(evt); };
        dbRequest.onblocked = function () { WinJS.log && WinJS.log("Database create blocked.", "PhotoDB", "error"); };

        // Reset the flag that indicates whether this is a new creation request. 
        // Assume that the database was previously created.
        newCreate = false;
        
        return dbRequest;
    }

    function deleteDB() {

        // Close and clear the handle to the database, held in the parent SdkSample namespace.
        if (PhotoDB.db) {
            PhotoDB.db.close();
        }
        PhotoDB.db = null;
        var dbRequest = window.indexedDB.deleteDatabase("PhotoDB");
        dbRequest.onerror = function () { WinJS.log && WinJS.log("Error deleting database.", "PhotoDB", "error"); };
        dbRequest.onsuccess = function () { WinJS.log && WinJS.log("Database deleted.", "PhotoDB", "status"); };
        dbRequest.onblocked = function () {
            WinJS.log && WinJS.log("Database delete blocked.", "PhotoDB", "error");
        };
    }

    function openDB(loadGalleryAtIndex, idx, options) {
        var dbRequest = window.indexedDB.open("PhotoDB", 1);

        // Add asynchronous callback functions
        dbRequest.onerror = function () { WinJS.log && WinJS.log("Error opening database.", "PhotoDB", "error"); };
        dbRequest.onupgradeneeded = function (evt) { WinJS.log && WinJS.log("Database wrong version.", "PhotoDB", "error"); if (PhotoDB.db) { PhotoDB.db.close(); } };
        dbRequest.onblocked = function () { WinJS.log && WinJS.log("Database access blocked.", "PhotoDB", "error"); };

        dbRequest.onsuccess = function (evt) {
            if (PhotoDB.db) {
                PhotoDB.db.close();
            }
            PhotoDB.db = evt.target.result;
            if (PhotoDB.db.objectStoreNames.length === 0) {
                WinJS.log && WinJS.log("Database schema does not exist. Complete the first scenario before continuing.", "PhotoDB", "error");
                PhotoDB.db.close();
                PhotoDB.db = null;
                window.indexedDB.deleteDatabase("PhotoDB", 1);
            } else {
                if (evt.type === "success") {
                    // Open our database tables.
                    var txn = PhotoDB.db.transaction(["Page", "Photo"], "readwrite");
                    txn.oncomplete = function () {
                        WinJS.log && WinJS.log("Database populated.", "PhotoDB", "status");
                        loadGalleryAtIndex(idx, options);
                    };
                    txn.onerror = function () {
                        WinJS.log && WinJS.log("Unable to populate database or database already populated.", "PhotoDB", "error");
                    };
                    txn.onabort = function () {
                        WinJS.log && WinJS.log("Unable to populate database or database already populated.", "PhotoDB", "error");
                    };
                }
            }
        };
    }

    // Whenever an IndexedDB is created, the version is set to "", but can be immediately upgraded by calling createDB. 
    function dbVersionUpgrade(evt) {

        // If the database was previously loaded, close it. 
        // Closing the database keeps it from becoming blocked for later delete operations.
        if (PhotoDB.db) {
            PhotoDB.db.close();
        }
        PhotoDB.db = evt.target.result;

        // Get the version update transaction handle, since we want to create the schema as part of the same transaction.
        var txn = evt.target.transaction;

        var gallery = PhotoDB.db.createObjectStore("Gallery", { keyPath: "name" });
        gallery.createIndex("name", "name", { unique: true });

        var url = PhotoDB.db.createObjectStore("Url", { keyPath: "url" });
        url.createIndex("name", "name", { unique: false });

        var page = PhotoDB.db.createObjectStore("Page", { keyPath: "url" });
        page.createIndex("groupURL", "group.url", { unique: false });

        var image = PhotoDB.db.createObjectStore("Image", { keyPath: "backgroundImage" });
        image.createIndex("pageURL", "pageURL", { unique: false });

        // Once the creation of the object stores is finished (they are created asynchronously), log success.
        txn.oncomplete = function () { WinJS.log && WinJS.log("Database schema created.", "PhotoDB", "status"); };
        newCreate = true;
    }

    function dbSuccess(evt) {

        // Log whether the app tried to create the database when it already existed. 
        if (!newCreate) {
            // Close this additional database request
            var db = evt.target.result;
            db.close();

            WinJS.log && WinJS.log("Database schema already exists.", "PhotoDB", "error");
            return;
        }
    }

    function initializeGallery(callback, params) {
        if (!PhotoDB.db) {
            var dbRequest = createDB();
            var oldSuccessCall = dbRequest.onsuccess;
            var oldUpgradeCall = dbRequest.onupgradeneeded;
            dbRequest.onsuccess = function (evt) {
                if (oldSuccessCall) {
                    oldSuccessCall(evt);
                }
                var openRequest = window.indexedDB.open("PhotoDB", 1);
                openRequest.onsuccess = function (evt) {
                    PhotoDB.db = evt.target.result;
                    populateData(PhotoDB.db);
                    callback(params);
                }
            }

            
        }
    }

    function populateData(db) {
        var galleries = Data.initializeGallery();
        var curGalleryIdx = 0;
        var request = null;

        if (!galleries || galleries.length == 0) {
            return;
        }

        var request = db.transaction(["Gallery"], "readwrite");
        for (var idx = 0; idx < galleries.length; ++idx) {
            request.objectStore("Gallery").add({
                name: galleries[idx].name,
                description: galleries[idx].desc,
                url: galleries[idx].url,
                backgroundImage: galleries[idx].backgroundImage,
                pageGroups: []
            });
        }
    }

    function updateImgSize(backgroundImg, width, height) {
        var txn = PhotoDB.db.transaction(["Image"], "readwrite");
        var request = txn.objectStore("Image").get(backgroundImg);
        request.onsuccess = function (evt) {
            var image = evt.target.result;
            if (!image) {
                return;
            }

            image.width = width;
            image.height = height;
            txn.objectStore("Image").put(image);
        }
    }

    function updateUrl(galleryName, urlItem) {
        var txn = PhotoDB.db.transaction(["Gallery"], "readwrite");
        var request = txn.objectStore("Gallery").get(galleryName);
        request.onsuccess = function (evt) {
            var gallery = evt.target.result;
            if (!gallery) {
                return;
            }

            if (gallery.pageGroup) {
                var urls = gallery.pageGroup;
                for (var idx = 0; idx < urls.length; ++urls) {
                    if (urls[idx].url == urlItem.url) {
                        urls[idx] = urlItem;
                    }
                }
                txn.objectStore("Gallery").put(gallery);
            }
        };
    }

    function updatePage(page) {
        var txn = PhotoDB.db.transaction(["Page"], "readwrite");
        txn.objectStore("Page").put(page);
    }

    function updateImage(image) {
        var txn = PhotoDB.db.transaction(["Image"], "readwrite");
        txn.objectStore("Image").put(image);
    }
})();
